﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AForge.Video.DirectShow;
using AForge.Video;
using System.Drawing;
using System.Configuration;
using ArcSoftFace.Utils;
//using ArcSoftFace.SDKUtil;
//using ArcSoftFace.SDKModels;
//using ArcSoftFace.Entity;
using AllInOne;
using System.Threading;
using AllInOne.Entity;

namespace AllInOne.Pages
{
    /// <summary>
    /// CameraPage.xaml 的交互逻辑
    /// </summary>
    public partial class CameraPage : Page
    {
        /// <summary>
        /// 父级窗口
        /// </summary>
        private MainWindow parent;


        public static string LIGHT_NORMAL;
        public static string LIGHT_PHOTO;

        /// <summary>
        /// 人脸比对通过阈值
        /// </summary>
        public static float FACE_VERIFY_THRESHOLD = 1;
        

        /// <summary>
        /// 摄像头配置(分辨率等)
        /// </summary>
        private VideoCapabilities videoCapabilities;

        /// <summary>
        /// 人脸对比标志
        /// </summary>
        public bool faceVerifyFlag { get; set; }

        /// <summary>
        /// 性别判断标志
        /// </summary>
        public bool genderVerifyFlag { get; set; }
        /// <summary>
        /// 人脸角度判断标志
        /// </summary>
        public bool takePhotoFlag { get; set; }

        public bool preparing { get; set; }

        public bool prepared { get; set; }

        public static string RGB_CAMERA_NAME;

        public static string IR_CAMERA_NAME;
        public static string PHOTO_CAMERA_NAME;
        public static string CAMERA_MODE = "001";
        



        /// <summary>
        /// 人脸追踪
        /// </summary>
        public bool faceTrackingFlag { get; set; }


        /// <summary>
        /// 身份证人脸特征
        /// </summary>
        private byte[] cardFeature = null;


        /// <summary>
        /// RGB人脸特征
        /// </summary>
        private byte[] rgbFeature = null;

        /// <summary>
        /// IR人脸特征
        /// </summary>
        private byte[] irFeature = null;



        public CameraPage()
        {
            InitializeComponent();
        }

        public CameraPage(MainWindow parent)
        {
            InitializeComponent();
            this.parent = parent;
        }

        public bool InitCamera()
        {
            this.takePhotoFlag = false;
            this.preparing = true;
            this.faceTrackingFlag = true;
            this.faceVerifyFlag = false;
            this.genderVerifyFlag = false;

            var initResult = BaiduAI.InitSdk(true);

            //初始化图像识别引擎
            if (!initResult)
            {
                MessageBox.Show("初始化图像识别引擎失败。"+initResult);
                return false;
            }

            //获取所有摄像头
            FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            //将sourcePlayer的视频源设置为0号摄像头
            if (videoDevices.Count > 0)
            {
                for (int v = 0; v < videoDevices.Count; v++)
                {
                    var videoDevice = videoDevices[v];
                    if (videoDevice.Name==PHOTO_CAMERA_NAME)
                    {
                        VideoCaptureDevice camera = new VideoCaptureDevice(videoDevice.MonikerString);
                        //设置摄像头分辨率
                        bool setSizeFlag = false;
                        for (int i = 0; i < camera.VideoCapabilities.Count(); i++)
                        {
                            //SimpleConsole.WriteInfo(string.Format("分辨率为{0}*{1}。", camera.VideoCapabilities[i].FrameSize.Height, camera.VideoCapabilities[i].FrameSize.Width), this);

                            if (camera.VideoCapabilities[i].FrameSize.Width == 1920)
                            {
                                this.videoCapabilities = camera.VideoCapabilities[i];
                                SimpleConsole.WriteInfo(string.Format("将摄像头<<{2}>>分辨率设置为{0}*{1}。", this.videoCapabilities.FrameSize.Height, this.videoCapabilities.FrameSize.Width, videoDevice.Name), this);
                                setSizeFlag = true;
                                break;
                            }
                        }
                        if (!setSizeFlag)
                        {
                            this.videoCapabilities = camera.VideoCapabilities[camera.VideoCapabilities.Count() - 1];
                            SimpleConsole.WriteInfo(string.Format("将摄像头<<{2}>>分辨率设置为{0}*{1}。", this.videoCapabilities.FrameSize.Height, this.videoCapabilities.FrameSize.Width, videoDevice.Name), this);
                        }
                        camera.VideoResolution = this.videoCapabilities;

                        this.sourcePlayer.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(photoFrameDelegate);

                        //设置视频源为当前摄像头
                        this.sourcePlayer.VideoSource = camera;
                        //摄像头启动
                        //this.sourcePlayer.Start();
                        SimpleConsole.WriteInfo("视频采集设备启动成功。", this);
                    }
                    else if (videoDevice.Name == RGB_CAMERA_NAME)
                    {
                        VideoCaptureDevice camera = new VideoCaptureDevice(videoDevice.MonikerString);
                        //设置摄像头分辨率
                        bool setSizeFlag = false;
                        for (int i = 0; i < camera.VideoCapabilities.Count(); i++)
                        {
                            //SimpleConsole.WriteInfo(string.Format("分辨率为{0}*{1}。", camera.VideoCapabilities[i].FrameSize.Height, camera.VideoCapabilities[i].FrameSize.Width), this);

                            if (camera.VideoCapabilities[i].FrameSize.Width == 800)
                            {
                                this.videoCapabilities = camera.VideoCapabilities[i];
                                SimpleConsole.WriteInfo(string.Format("将摄像头<<{2}>>分辨率设置为{0}*{1}。", this.videoCapabilities.FrameSize.Height, this.videoCapabilities.FrameSize.Width, videoDevice.Name), this);
                                setSizeFlag = true;
                                break;
                            }
                        }
                        if (!setSizeFlag)
                        {
                            this.videoCapabilities = camera.VideoCapabilities[camera.VideoCapabilities.Count() - 1];
                            SimpleConsole.WriteInfo(string.Format("将摄像头<<{2}>>分辨率设置为{0}*{1}。", this.videoCapabilities.FrameSize.Height, this.videoCapabilities.FrameSize.Width, videoDevice.Name), this);
                        }
                        camera.VideoResolution = this.videoCapabilities;
                        this.rgbSourcePlayer.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(rgbFrameDelegate);

                        //设置视频源为当前摄像头
                        this.rgbSourcePlayer.VideoSource = camera;
                        //摄像头启动
                        
                    }

                    else if (videoDevice.Name == IR_CAMERA_NAME)
                    {
                        VideoCaptureDevice camera = new VideoCaptureDevice(videoDevice.MonikerString);
                        //设置摄像头分辨率
                        bool setSizeFlag = false;
                        for (int i = 0; i < camera.VideoCapabilities.Count(); i++)
                        {
                            //SimpleConsole.WriteInfo(string.Format("分辨率为{0}*{1}。", camera.VideoCapabilities[i].FrameSize.Height, camera.VideoCapabilities[i].FrameSize.Width), this);

                            if (camera.VideoCapabilities[i].FrameSize.Width == 800)
                            {
                                this.videoCapabilities = camera.VideoCapabilities[i];
                                SimpleConsole.WriteInfo(string.Format("将摄像头<<{2}>>分辨率设置为{0}*{1}。", this.videoCapabilities.FrameSize.Height, this.videoCapabilities.FrameSize.Width, videoDevice.Name), this);
                                setSizeFlag = true;
                                break;
                            }
                        }
                        if (!setSizeFlag)
                        {
                            this.videoCapabilities = camera.VideoCapabilities[camera.VideoCapabilities.Count() - 1];
                            SimpleConsole.WriteInfo(string.Format("将摄像头<<{2}>>分辨率设置为{0}*{1}。", this.videoCapabilities.FrameSize.Height, this.videoCapabilities.FrameSize.Width, videoDevice.Name), this);
                        }
                        camera.VideoResolution = this.videoCapabilities;
                        this.irSourcePlayer.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(irFrameDelegate);

                        //设置视频源为当前摄像头
                        this.irSourcePlayer.VideoSource = camera;
                        //摄像头启动
                        //this.irSourcePlayer.Start();
                    }

                    if (CAMERA_MODE == "111")
                    {
                        this.sourcePlayerContainer.Visibility = Visibility.Hidden;
                        this.rgbSourcePlayerContainer.Visibility = Visibility.Visible;
                        rgbSourcePlayer.Start();
                    }
                    else if (CAMERA_MODE == "111")
                    {
                        this.sourcePlayerContainer.Visibility = Visibility.Hidden;
                        this.rgbSourcePlayerContainer.Visibility = Visibility.Visible;
                        rgbSourcePlayer.Start();
                    }
                    else if (CAMERA_MODE == "001")
                    {
                        this.sourcePlayerContainer.Visibility = Visibility.Visible;
                        this.rgbSourcePlayerContainer.Visibility = Visibility.Hidden;
                        sourcePlayer.Start();
                    }
                }


            }
            else {
                SimpleConsole.WriteInfo("未检测到视频采集设备。", this);
                MessageBox.Show("未检测到视频采集设备。");
                this.parent.SetError("未检测到视频采集设备。");
            }

            return true;
        }






        public void DisConnect()
        {
            if (sourcePlayer.VideoSource != null)
            {
                sourcePlayer.SignalToStop();
                sourcePlayer.WaitForStop();
                sourcePlayer.VideoSource = null;
            }
        }

        
        /// <summary>
        /// 人脸比对
        /// </summary>
        int verifyFailedCount = 0;


        private object locker = new object();
        private bool inProgress = false;


        private int faceLeft;
        private int faceTop;
        private int faceWidth;
        private int faceHeight;




        /// <summary>
        /// 对比人脸
        /// </summary>
        /// <param name="photo">实时人脸</param>
        /// <returns>相似度</returns>
        private float compareFace(Bitmap photo)
        {

            float similarity = -1;
            byte[] photoBytes = ImageUtil.img2byte(photo);
            similarity = BaiduAI.CompareFace(cardFeature, photoBytes);

            SimpleConsole.WriteInfo(string.Format("人脸相似度：{0}", similarity),this);

            return similarity;
        }





        
        private Queue<double> rollQueue = new Queue<double>();
        private Queue<double> pitchQueue = new Queue<double>();
        private Queue<double> yawQueue = new Queue<double>();

        private long lastTipsTime = 0;
        private float yawThreshold = 6;
        private float yawBaseline = 0;


        private float rollThreshold = 5;
        private float rollBaseline = 0;
        private float pitchThreshold = 7;
        private float pitchBaseline = 10;

        private float faceXBaseline = 0.5f;
        private float faceYBaseline = 0.5f;
        private float faceXThreshold = 0.1f;
        private float faceYThreshold = 0.08f;
         

        private Queue<double> faceXQueue = new Queue<double>();
        private Queue<double> faceYQueue = new Queue<double>();
        public static int MOVE_SPEED = 380;

        private bool moving = false;
        //private bool moved = false;

       

        private void Border_MouseUp(object sender, MouseButtonEventArgs e)
        {
            moving = true;

        }


        private byte lastMoveFlag;

        public void MoveCompleted(byte flag)
        {

            lastMoveFlag = flag;
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                moving = false;
                this.txtMoveTips.Text = "移动完成";
            }));
        }


        public void setMoveTips(string tips)
        {
            this.Dispatcher.Invoke(new Action(delegate () {
                this.txtMoveTips.Text = tips;
            }));
        }

        public void setTips(string tips)
        {
            this.Dispatcher.Invoke(new Action(delegate () {
                this.txtTips.Text = tips;
            }));
        }


        /// <summary>
        /// 检查拍照是否准备完成
        /// </summary>
        /// <param name="faceInfo3D"></param>
        /// <param name="image"></param>
        /// <param name="faceRect"></param>
        /// <returns></returns>
        private bool checkPrepared(FaceInfo faceInfo,Bitmap image)
        {


            double faceY = faceInfo.y*1.0/image.Height;

            double avgFaceY = getAvg(faceYQueue, faceY);

           
            if (moving)
            {
                return false;
            }

            if (faceYQueue.Count >= 10)
            {


                if (Math.Abs(avgFaceY - faceYBaseline) > faceYThreshold)
                {




                    int step = (int)(MOVE_SPEED * Math.Abs(avgFaceY - faceYBaseline));
                    if (avgFaceY < faceYBaseline)
                    {
                        if (lastMoveFlag == 1)
                        {
                            long now = DateTime.Now.Ticks;
                            if (now - lastTipsTime > 50000000)
                            {
                                lastTipsTime = now;
                                this.parent.PlaySound(Properties.Resources.male_move_down, Properties.Resources.female_move_down);
                            }
                            return false;
                        }
                        this.setMoveTips(string.Format("相机向上移动{0}单位", step));
                        this.parent.SendMsgToScm(new byte[] { 0x24, 0x14, 0x18, 0xd3, (byte)step, 0x0d, 0x0a });
                        
                    }
                    else
                    {
                        if (lastMoveFlag == 2)
                        {
                            long now = DateTime.Now.Ticks;
                            if (now - lastTipsTime > 50000000)
                            {
                                lastTipsTime = now;
                                this.parent.PlaySound(Properties.Resources.male_move_up, Properties.Resources.female_move_up);
                            }
                            return false;
                        }
                        this.setMoveTips(string.Format("相机向下移动{0}单位", step));
                        this.parent.SendMsgToScm(new byte[] { 0x24, 0x15, 0x18, 0xd2, (byte)step, 0x0d, 0x0a });
                        
                    }
                    moving = true;

                    return false;
                }

            }


            //如果开始时间小于7.5秒
            if (DateTime.Now.Ticks - photoStartTime < 75000000)
            {
                return false;
            }





            double faceX = faceInfo.x*1.0/image.Width;

            double avgFaceX = getAvg(faceXQueue, faceX);
            double avgYaw = getAvg(yawQueue, faceInfo.yaw);
            double avgPitch = getAvg(pitchQueue, faceInfo.pitch);
            double avgRoll = getAvg(rollQueue, faceInfo.roll);

            if (faceXQueue.Count >= 10)
            {
                if (Math.Abs(avgFaceX - faceXBaseline) > faceXThreshold)
                {
                    long now = DateTime.Now.Ticks;
                    if (now - lastTipsTime > 50000000)
                    {
                        lastTipsTime = now;
                        faceXQueue.Clear();
                        if (avgFaceX < faceXBaseline)
                        {
                            //提示身体向右移动
                            this.parent.PlaySound(Properties.Resources.male_move_right, Properties.Resources.female_move_right);
                            this.setTips("身体向右移动");
                        }
                        else
                        {
                            //提示身体向左移动
                            this.parent.PlaySound(Properties.Resources.male_move_left, Properties.Resources.female_move_left);
                            this.setTips("身体向左移动");

                        }
                    }
                    return false;
                }
            }
            else
            {
                return false;
            }

            if (yawQueue.Count >= 10)
            {
                if (Math.Abs(avgYaw - yawBaseline) > yawThreshold || Math.Abs(faceInfo.yaw - yawBaseline) > yawThreshold)
                {
                    long now = DateTime.Now.Ticks;
                    if (now - lastTipsTime > 50000000)
                    {
                        lastTipsTime = now;
                        yawQueue.Clear();
                        if (avgYaw > yawBaseline|| faceInfo.yaw>yawBaseline)
                        {
                            //提示向右转头
                            this.parent.PlaySound(Properties.Resources.male_yaw_right, Properties.Resources.female_yaw_right);
                            this.setTips("头稍向右转动");
                        }
                        else
                        {
                            //提示向左转头
                            this.parent.PlaySound(Properties.Resources.male_yaw_left, Properties.Resources.female_yaw_left);
                            this.setTips("头稍向左转动");

                        }
                    }
                    return false;
                }
            }
            else {
                return false;
            }


            if (pitchQueue.Count >= 10)
            {
                if (Math.Abs(avgPitch - pitchBaseline) > pitchThreshold)
                {
                    long now = DateTime.Now.Ticks;
                    if (now - lastTipsTime > 50000000)
                    {
                        lastTipsTime = now;
                        pitchQueue.Clear();
                        if (avgPitch > pitchBaseline)
                        {
                            //提示抬头
                            this.parent.PlaySound(Properties.Resources.male_pitch_up, Properties.Resources.female_pitch_up);
                            this.setTips("稍抬头");

                        }
                        else
                        {
                            //提示低头
                            this.parent.PlaySound(Properties.Resources.male_pitch_down, Properties.Resources.female_pitch_down);
                            this.setTips("稍低头");

                        }
                    }
                    return false;
                }
            }
            else
            {
                return false;
            }

            if (rollQueue.Count >= 10)
            {
                if (Math.Abs(avgRoll - rollBaseline) > rollThreshold)
                {
                    long now = DateTime.Now.Ticks;
                    if (now - lastTipsTime > 50000000)
                    {
                        lastTipsTime = now;
                        rollQueue.Clear();
                        if (avgRoll < rollBaseline)
                        {
                            //提示向右倾斜
                            this.parent.PlaySound(Properties.Resources.male_roll_right, Properties.Resources.female_roll_right);
                            this.setTips("头稍向右倾斜");

                        }
                        else
                        {
                            //提示向左倾斜
                            this.parent.PlaySound(Properties.Resources.male_roll_left, Properties.Resources.female_roll_left);
                            this.setTips("头稍向左倾斜");
                        }
                    }
                    return false;
                }
            }
            else
            {
                return false;
            }


            return true;
        }

        private double getAvg(Queue<double> queue, double newValue)
        {
            if (queue.Count >= 10)
            {
                queue.Dequeue();
            }
            queue.Enqueue(newValue);
            return queue.Average();
        }


        Bitmap currentPhoto = null;
        object currentPhotoLocker = new object();    

        private int count = 1;
        private void takePhoto(FaceInfo faceInfo, Bitmap image)
        {

            //准备中
            if (preparing)
            {
                //判断准备情况
                preparing = !checkPrepared(faceInfo, image);
            }
            //准备完成
            else
            {
                if (!prepared)
                {

                    SimpleConsole.WriteInfo(count.ToString(), this);
                    count++;
                    prepared = true;
                    //开始采集照片
                    this.parent.PlaySound(Properties.Resources.male_start_take_photo, Properties.Resources.female_start_take_photo);
                    this.setTips("平视镜头,开始拍照");
                    startPhotoThread();
                }

                
            }
        }

        private Thread photoThread;

        private void startPhotoThread()
        {


            


            photoThread = new Thread(new ThreadStart(delegate () {
                

                Thread.Sleep(4500);



                this.parent.ShowChoosePhotoPage();
                this.parent.PlaySound(Properties.Resources.male_photo1, Properties.Resources.female_photo1);
                this.setTips("第1张");
                Thread.Sleep(1000);
                this.parent.PlaySound(Properties.Resources.take_photo, Properties.Resources.take_photo);

                this.bling(0);


                Thread.Sleep(300);
                this.parent.PlaySound(Properties.Resources.male_photo2, Properties.Resources.female_photo2);
                this.setTips("第2张");
                Thread.Sleep(1000);
                this.parent.PlaySound(Properties.Resources.take_photo, Properties.Resources.take_photo);


                this.bling(1);
                Thread.Sleep(300);
                this.parent.PlaySound(Properties.Resources.male_photo3, Properties.Resources.female_photo3);
                this.setTips("第3张");
                Thread.Sleep(1000);
                this.parent.PlaySound(Properties.Resources.take_photo, Properties.Resources.take_photo);

                this.bling(2);
                this.StopPhoto();
                this.setTips("拍照结束");
               
            })) { IsBackground = true };
            photoThread.Start();
        }


        public static Bitmap handlePhoto(Bitmap source)
        {
            FaceInfo faceInfo = BaiduAI.TrackFace(ImageUtil.img2byte(source));

            if (faceInfo != null)
            {
                int left = (int)(faceInfo.x - faceInfo.width * 0.66 / PHOTO_ZOOM);
                int top = (int)(faceInfo.y - faceInfo.width * 1.06 / PHOTO_ZOOM);
                int right = (int)(faceInfo.x + faceInfo.width * 0.66 / PHOTO_ZOOM);
                int bottom = (int)(faceInfo.y + faceInfo.width * 0.86 / PHOTO_ZOOM);
                Bitmap photo = (Bitmap)ImageUtil.CutImage(source, left, top, right, bottom);
                source.Dispose();
                return photo;
            }
            else {
                Bitmap result = (Bitmap)source.Clone();
                source.Dispose();
                return result;
            }
        }



        private void bling(int index)
        {
            Thread.Sleep(1200);
            Bitmap photo = null;
            lock (currentPhotoLocker) {
                photo = handlePhoto((Bitmap)this.currentPhoto.Clone());
            }
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                this.sourcePlayerContainer.Visibility = Visibility.Hidden;

                this.maskWhite.Visibility = Visibility.Visible;
                this.imagePhoto.Source = ImageUtil.BitmapToBitmapImage(photo);
            }));
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                this.maskBlack.Visibility = Visibility.Visible;
                this.maskWhite.Visibility = Visibility.Hidden;
                this.imagePhoto.Visibility = Visibility.Visible;
            }));
            for (int i = 0; i <= 20; i++)
            {
                Thread.Sleep(20);
                var opacity = 1 - 0.05 * i;
                this.Dispatcher.Invoke(new Action(delegate ()
                {
                    this.maskBlack.Opacity = opacity;
                }));
            }


            Thread.Sleep(300);


            for (int i = 20; i >= 0; i--)
            {
                this.Dispatcher.Invoke(new Action(delegate ()
                {
                    Thread.Sleep(20);
                    var opacity = 1 - 0.05 * i;
                    this.maskBlack.Opacity = opacity;
                }));
            }
            Thread.Sleep(300);
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                this.maskWhite.Visibility = Visibility.Visible;
                this.maskBlack.Visibility = Visibility.Hidden;
            }));
            Thread.Sleep(300);
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                this.maskWhite.Visibility = Visibility.Hidden;
            }));
            Thread.Sleep(300);
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                this.imagePhoto.Visibility = Visibility.Hidden;
                this.sourcePlayerContainer.Visibility = Visibility.Visible;
            }));
            this.parent.AddPhotoToBeChoosed(photo);
            
        }

        



        public static float PHOTO_ZOOM = 1.0f;



        private void rgbHandleFrame(Bitmap image)
        {



            //加锁
            lock (locker)
            {
                if (inProgress)
                {
                    image.Dispose();
                    return;
                }
                inProgress = true;
            }

            this.parent.Dispatcher.Invoke(new Action(delegate
            {
                this.parent.SetVideoFrame(image);
            }));


            byte[] imageBytes = ImageUtil.img2byte(image);

            FaceInfo trackFaceInfo = BaiduAI.TrackFace(imageBytes);


            //如果识别到人脸
            if (trackFaceInfo != null)
            {


                this.parent.SendMsgToController(new byte[] { 0xaa, 0xb1, 0x01, 0x01, 0x00, 0x00, 0x00, 0xdd });  //有人
                this.parent.ResetIdelTime();


                //获取人脸框

                faceWidth = trackFaceInfo.width;
                faceHeight = (int)(trackFaceInfo.width * 1);
                faceLeft = trackFaceInfo.x - faceWidth / 2;
                faceTop = trackFaceInfo.y - faceHeight / 2;


                //截取人脸图片
                //人脸相似度
                float similarity = 0;


                if (genderVerifyFlag || faceVerifyFlag)
                {




                    Bitmap photo = (Bitmap)ImageUtil.CutImage(image, faceLeft, faceTop, faceLeft + faceWidth, faceTop + faceHeight);

                    byte[] photoBytes = ImageUtil.img2byte(photo);

                    //判断性别年龄
                    if (genderVerifyFlag)
                    {
                        FaceInfo genderFaceInfo = BaiduAI.GetFaceAttr(photoBytes);
                        if (genderFaceInfo != null && genderFaceInfo.genderConf > 0.95)
                        {
                            this.parent.setFaceGender(genderFaceInfo.gender);

                        }
                    }


                    if (faceVerifyFlag)
                    {

                        similarity = compareFace(image);
                        if (similarity >= FACE_VERIFY_THRESHOLD)
                        //if(true)
                        {
                            rgbFeature = ImageUtil.img2byte(image);
                            FaceInfo livenessFaceInfo = BaiduAI.RgbIrLiveness(rgbFeature, irFeature);
                            Console.WriteLine(string.Format("irScore:{0},rgbScore:{1}", livenessFaceInfo.irScore, livenessFaceInfo.rgbScore));
                            if (livenessFaceInfo.irScore >0.6 || livenessFaceInfo.rgbScore > 0.7)
                            {
                                this.parent.Dispatcher.Invoke(new Action(delegate ()
                                {
                                    this.parent.SetFaceVerifyResult(true, ImageUtil.BitmapToString(image));
                                }));
                                this.StopVerify();
                            }
                            else {
                                verifyFailedCount++;
                                if (verifyFailedCount >= 10)
                                {

                                    this.parent.Dispatcher.Invoke(new Action(delegate ()
                                    {
                                        this.parent.SetFaceVerifyResult(false, ImageUtil.BitmapToString(photo));
                                    }));
                                    //MessageBox.Show("人证核验失败");
                                    this.StopVerify();
                                }
                            }
                        }
                        else
                        {
                            verifyFailedCount++;
                            if (verifyFailedCount >= 10)
                            {

                                this.parent.Dispatcher.Invoke(new Action(delegate ()
                                {
                                    this.parent.SetFaceVerifyResult(false, ImageUtil.BitmapToString(photo));
                                }));
                                //MessageBox.Show("人证核验失败");
                                this.StopVerify();
                            }
                        }

                    }
                    photo.Dispose();
                }
            }
            else
            {
                this.parent.SendMsgToController(new byte[] { 0xaa, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdd }); //无人

                faceLeft = 0;
                faceTop = 0;
                faceWidth = 0;
                faceHeight = 0;
            }

            //解锁
            lock (locker)
            {
                image.Dispose();
                inProgress = false;
            }
        }

        /// <summary>
        /// 处理图像
        /// </summary>
        /// <param name="image"></param>
        private void photoHandleFrame(Bitmap image)
        {
            if (!takePhotoFlag&&CAMERA_MODE[0]=='1')
            {
                return;
            }


            //加锁
            lock (locker)
            {
                if (inProgress)
                {
                    image.Dispose();
                    return;
                }
                inProgress = true;
            }

            this.parent.Dispatcher.Invoke(new Action(delegate
            {
                this.parent.SetVideoFrame(image);
            }));


            byte[] imageBytes = ImageUtil.img2byte(image);

            FaceInfo trackFaceInfo = BaiduAI.TrackFace(imageBytes);


            //如果识别到人脸
            if (trackFaceInfo!=null)
            {

                
                this.parent.SendMsgToController(new byte[] { 0xaa, 0xb1, 0x01, 0x01, 0x00, 0x00, 0x00, 0xdd });  //有人
                this.parent.ResetIdelTime();


                //获取人脸框

                faceWidth = trackFaceInfo.width;
                faceHeight = (int)(trackFaceInfo.width * 1);
                faceLeft = trackFaceInfo.x-faceWidth/2;
                faceTop = trackFaceInfo.y - faceHeight / 2;


                //截取人脸图片
                //人脸相似度
                float similarity = 0;


                if (takePhotoFlag || genderVerifyFlag || faceVerifyFlag)
                {




                    Bitmap photo = (Bitmap)ImageUtil.CutImage(image, faceLeft, faceTop, faceLeft + faceWidth, faceTop + faceHeight);

                    byte[] photoBytes = ImageUtil.img2byte(photo);

                    //判断性别年龄
                    if (genderVerifyFlag&&CAMERA_MODE[0]!=1)
                    {
                        FaceInfo genderFaceInfo = BaiduAI.GetFaceAttr(photoBytes);
                        if (genderFaceInfo!=null && genderFaceInfo.genderConf>0.95)
                        {
                            this.parent.setFaceGender(genderFaceInfo.gender);

                        }
                    }

                    //拍照
                    if (takePhotoFlag)
                    {

                        this.takePhoto(trackFaceInfo, image);

                    }


                    if (faceVerifyFlag && CAMERA_MODE[0] != 1)
                    {

                        similarity = compareFace(image);
                        if (similarity >= FACE_VERIFY_THRESHOLD)
                        //if(true)
                        {
                            this.parent.Dispatcher.Invoke(new Action(delegate ()
                            {
                                this.parent.SetFaceVerifyResult(true, ImageUtil.BitmapToString(image));
                            }));
                            this.StopVerify();
                        }
                        else
                        {
                            verifyFailedCount++;
                            if (verifyFailedCount >= 10)
                            {

                                this.parent.Dispatcher.Invoke(new Action(delegate ()
                                {
                                    this.parent.SetFaceVerifyResult(false, ImageUtil.BitmapToString(photo));
                                }));
                                //MessageBox.Show("人证核验失败");
                                this.StopVerify();
                            }
                        }

                    }
                    photo.Dispose();
                }
            }
            else {
                this.parent.SendMsgToController(new byte[] { 0xaa, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdd }); //无人

                faceLeft = 0;
                faceTop = 0;
                faceWidth = 0;
                faceHeight = 0;
            }

            //解锁
            lock (locker)
            {
                image.Dispose();
                inProgress = false;
            }
        }



        private float frameWidth = 568;
        private float frameHeight = 770;



        private Bitmap cutImageByFrameSizeFlip(Bitmap image, double width, double height)
        {

            int left = (int)(image.Width - width * image.Height / height) / 2;
            int top = 0;
            int right = (image.Width - left);
            int bottom = image.Height;
            return (Bitmap)ImageUtil.CutImage(image, left, top, right, bottom);
        }

        int irCount = 0;

        private void irFrameDelegate(object sender, ref Bitmap image)
        {
            if (irCount>=2)
            {
                irCount = 0;
                image = this.cutImageByFrameSizeFlip(image, frameWidth, frameHeight);
                irFeature = ImageUtil.img2byte(image);
                return;
            }
            irCount++;
        }

        private void rgbFrameDelegate(object sender, ref Bitmap image)
        {
            image = this.cutImageByFrameSizeFlip(image, frameWidth, frameHeight);

            Bitmap imageClone = (Bitmap)image.Clone();
            new Thread(new ThreadStart(delegate ()
            {
                rgbHandleFrame(imageClone);
            }))
            { IsBackground = true }.Start();

            if (faceTrackingFlag && faceHeight > 0 && faceWidth > 0)
            {
                image = (Bitmap)ImageUtil.MarkRect(image, faceLeft, faceTop, faceWidth, faceHeight);
            }

        }


        /// <summary>
        /// 处理视频帧
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="image"></param>
        private void photoFrameDelegate(object sender, ref Bitmap image)
        {

            ////图像旋转90

            long time1 = DateTime.Now.Ticks;
            bool exceptionFlag = false;
            try
            {
                image.RotateFlip(RotateFlipType.Rotate270FlipX);

            }
            catch (Exception e)
            {
                exceptionFlag = true;
                SimpleConsole.WriteError(e.Message + e.StackTrace, this);
            }
            long time2 = DateTime.Now.Ticks;
            //Console.WriteLine("旋转画面时间:{0}", (time2 - time1)/10000);
            image = this.cutImageByFrameSize(image, frameWidth, frameHeight);
            long time3 = DateTime.Now.Ticks;
            //Console.WriteLine("剪切画面时间:{0}", (time3 - time2) / 10000);

            ////image = (Bitmap)ImageUtil.CutImage(image,90,258,630,1022);

            if (!exceptionFlag)
            {
                Bitmap imageClone = (Bitmap)image.Clone();
                new Thread(new ThreadStart(delegate ()
                {
                    photoHandleFrame(imageClone);
                }))
                { IsBackground = true }.Start();

                if (takePhotoFlag)
                {
                    lock (currentPhotoLocker)
                    {
                        if (this.currentPhoto != null)
                        {
                            this.currentPhoto.Dispose();
                        }
                        this.currentPhoto = (Bitmap)image.Clone();
                    }
                }
            }

            //标记人脸
            if (faceTrackingFlag && faceHeight > 0 && faceWidth > 0)
            {
                image = (Bitmap)ImageUtil.MarkRect(image, faceLeft, faceTop, faceWidth, faceHeight);
            }

            long time4 = DateTime.Now.Ticks;
            //Console.WriteLine("总时间:{0}", (time4 - time1) / 10000);
        }

        public static float CAMERA_ZOOM = 0.75f;

        private Bitmap cutImageByFrameSize(Bitmap image,double width,double height)
        {

            int left = (int)(image.Width * (1 - CAMERA_ZOOM) / 2);
            int top = (int)((image.Height - image.Width * height / width) * CAMERA_ZOOM / 2 + (1- CAMERA_ZOOM) *image.Height/2);
            int right = (image.Width - left);
            int bottom = image.Height - top;
            return (Bitmap)ImageUtil.CutImage(image, left, top, right, bottom);
        }





        /// <summary>
        /// 获取照片特征值
        /// </summary>
        /// <param name="photo"></param>
        /// <returns></returns>
        public byte[] GetPhotoFeature(System.Drawing.Image photo)
        {
            //System.Drawing.Image cardPhot = System.Drawing.Image.FromFile("");


            cardFeature = ImageUtil.img2byte(photo);

            return cardFeature;
        }


        private long photoStartTime;

        public bool StartPhoto() {

            this.Dispatcher.Invoke(new Action(delegate ()
            {

                    this.sourcePlayerContainer.Visibility = Visibility.Visible;
                    this.rgbSourcePlayerContainer.Visibility = Visibility.Hidden;
                    rgbSourcePlayer.SignalToStop();
                    irSourcePlayer.SignalToStop();
                    sourcePlayer.Start();
                
            }));


            if (this.photoThread!=null&&this.photoThread.IsAlive)
            {
                return false;
            }


            byte switch1 = byte.Parse(LIGHT_PHOTO.Substring(0, 1));
            byte switch2 = byte.Parse(LIGHT_PHOTO.Substring(2, 1));
          


            this.parent.SetController(1, switch1);
            this.parent.SetController(2, switch2);

            this.StartCamera();
            this.genderVerifyFlag = false;
            this.faceTrackingFlag = false;
            this.takePhotoFlag = true;
            this.preparing = true;
            this.prepared = false;
            //this.moved = false;
            this.moving = false;
            photoStartTime = DateTime.Now.Ticks;
            this.parent.PlaySound(Properties.Resources.male_prepare_take_photo, Properties.Resources.female_prepare_take_photo);
            return true;
        }

        public void StopPhoto()
        {

            this.Dispatcher.Invoke(new Action(delegate ()
            {
                if (CAMERA_MODE == "111" )
                {
                    this.sourcePlayerContainer.Visibility = Visibility.Hidden;
                    this.rgbSourcePlayerContainer.Visibility = Visibility.Visible;
                    rgbSourcePlayer.Start();
                    irSourcePlayer.Start();
                    sourcePlayer.SignalToStop();
                }
            }));

            byte switch1 = byte.Parse(LIGHT_NORMAL.Substring(0, 1));
            byte switch2 = byte.Parse(LIGHT_NORMAL.Substring(2, 1));

            this.parent.SetController(1, switch1);
            this.parent.SetController(2, switch2);
            this.takePhotoFlag = false;
        }

       




        public void StartVerify(byte[] cardFeature)
        {
            this.StartCamera();
            this.cardFeature = cardFeature;
            this.verifyFailedCount = 0;
            this.faceTrackingFlag = true;
            this.faceVerifyFlag = true;
            this.genderVerifyFlag = false;
            this.takePhotoFlag = false;



            this.Dispatcher.Invoke(new Action(delegate ()
            {
                if (CAMERA_MODE == "111" || CAMERA_MODE == "110")
                {
                    this.sourcePlayerContainer.Visibility = Visibility.Hidden;
                    this.rgbSourcePlayerContainer.Visibility = Visibility.Visible;
                    rgbSourcePlayer.Start();
                    irSourcePlayer.Start();
                }
            }));


        }

        public void StartVerify()
        {
            this.StartCamera();
            this.verifyFailedCount = 0;
            this.faceTrackingFlag = true;
            this.faceVerifyFlag = true;
            this.genderVerifyFlag = false;
            this.takePhotoFlag = false;

            this.Dispatcher.Invoke(new Action(delegate ()
            {
                if (CAMERA_MODE == "111" || CAMERA_MODE == "110")
                {
                    this.sourcePlayerContainer.Visibility = Visibility.Hidden;
                    this.rgbSourcePlayerContainer.Visibility = Visibility.Visible;
                    rgbSourcePlayer.Start();
                    irSourcePlayer.Start();
                }
            }));

            
        }


        public void StopVerify()
        {
            this.verifyFailedCount = 0;
            this.faceTrackingFlag = false;
            this.faceVerifyFlag = false;


           
            
        }


        public void StartVerifyGender()
        {
            this.StartCamera();
            this.genderVerifyFlag = true;
            this.faceTrackingFlag = false;
            this.faceVerifyFlag = false;
            this.takePhotoFlag = false;
        }

        public void StopPhotoThread() {
            if (this.photoThread!=null&&this.photoThread.IsAlive)
            {
                this.photoThread.Abort();
            }
        }

        public void StopVerifyGender() {
            this.genderVerifyFlag = false;
        }


        private bool cameraRunningFlag = false;

        public void StopCamera()
        {
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                cameraRunningFlag = false;
                this.sourcePlayer.Stop();
            }));
        }

        public void StartCamera()
        {
            this.Dispatcher.Invoke(new Action(delegate ()
            {
                if (!cameraRunningFlag)
                {
                    this.sourcePlayer.Start();
                    cameraRunningFlag = true;
                }
            }));
        }

    }
}
